#ifndef __INVADER_FRAME_H__
#define __INVADER_FRAME_H__

#include <map>

#include <QFrame>

class QLabel;
class QTimer;

class Tank;
class TankBullet;
class InvaderArmy;
class InvaderBullet;
class InvaderLabel;
class Bunker;

/**
 * The main frame which implements all of the game logic
 */
class InvaderFrame : public QFrame
{
  Q_OBJECT

public:
  /**
   * @param parent parent of the InvaderFrame
   */
  InvaderFrame (QWidget *parent = 0);

public slots:
  /**
   * Starts the game
   */
  void start ();
  /**
   * Stops the game
   */
  void stop ();
  /**
   * Pause/Unpauses the game
   */
  void pause ();
  /**
   * Resets the game
   *
   * @param demoMode when true the game will run in demo or attract mode
   */
  void reset (bool demoMode = false);

signals:
  /**
   * Emitted when the score changes
   *
   * @param score new score
   */
  void scoreChanged (int score);
  /**
   * Emitted when the number of lives left changes
   *
   * @param lives the number of lives left
   */
  void livesChanged (int lives);
  /**
   * Emitted when the in game menu should be displayed
   */
  void displayMenu ();
  /**
   * Emitted when a game is over
   */
  void gameOver ();
  /**
   * Emitted when the demo mode ends
   */
  void endDemoMode ();

private slots:
  void animationTimerTimeout ();
  void armyFrameChanged ();
  void armyInvaderKilled (int score);
  void armyShoots (QPoint location);
  void pauseBlinkTimerTimeout ();

protected:
  virtual void resizeEvent (QResizeEvent *event);
  virtual void keyPressEvent (QKeyEvent *event);
  virtual void keyReleaseEvent (QKeyEvent *event);
  virtual void mouseMoveEvent (QMouseEvent *event);
  virtual void mousePressEvent (QMouseEvent *event);
  virtual void mouseReleaseEvent (QMouseEvent *event);

private:
  InvaderArmy *_army;
  int _armyMovement;
  int _armyHeight;
  std::list<InvaderBullet *> _invaderBullets;
  int _lives;
  TankBullet *_tankBullet;
  bool _fireBullet;
  Tank *_tank;
  int _moveTankDPos;
  QPoint _desiredTankPosition;
  QTimer *_animationTimer;
  std::multimap<int, Bunker *> _bunkers;
  int _bunkerWidth;
  int _score;
  InvaderLabel *_pauseLabel;
  QTimer *_pauseBlinkTimer;
  bool _demoMode;
  Tank *_mysteryShip;
  int _mysteryShipMovement;

  void removeInvaderBullet (std::list<InvaderBullet *>::iterator &bullet);
};

#endif
